package com.xbongbong.paas.script.controller;

import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.errorcodes.SettleAccountErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.product.pojo.dto.SettleAccountsDTO;
import com.xbongbong.pro.product.pojo.vo.SettleAccountsVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.domain.entity.SettleAccountsEntity;
import com.xbongbong.saas.model.SettleAccountsModel;
import com.xbongbong.saas.service.SettleAccountsService;
import com.xbongbong.sys.domain.entity.FeeCompanyEntity;
import com.xbongbong.sys.help.SysEnvHelp;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.FeeCompanyModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 结账脚本<p>
 * 代码描述<p>
 * Company: 逍邦网络科技有限公司<p>
 *
 * @author ruansicheng
 * @version v1.0
 * @since 2021-11-30 14:33
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/settleAccounts")
public class SettleAccountsScriptController {
    private static final Logger LOG = LoggerFactory.getLogger(SettleAccountsScriptController.class);
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private SettleAccountsService settleAccountsService;
    @Resource
    private SettleAccountsModel settleAccountsModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private FeeCompanyModel feeCompanyModel;
    @Resource
    private SysEnvHelp sysEnvHelp;

    /**
     * 自动结账
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/automatic", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String automaticSettleAccounts(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        LOG.warn("自动结账 begin。。。。。。。");
        long start = DateTimeUtil.getInt();
        List<String> errorCorpidList = new ArrayList<>();
        List<String> corpidList = new ArrayList<>();
        //支持传入公司
        if (CollectionsUtil.isNotEmpty(fixDataJobDTO.getCorpidList())) {
            corpidList = fixDataJobDTO.getCorpidList();
        }else {
            //获取符合条件的公司-现在开启进销存公司列表
            corpidList = companyModel.getJxcCorpidListByActive();
        }
        LOG.warn("共有公司" + corpidList.size() + "家");
        LOG.warn("查询进销存公司列表结束，花费时间:" + (DateTimeUtil.getInt() - start));
        //获取两个月前的日期
        Long twoMonthAgo = DateTimeUtil.getTimestampByCalendarType(DateTimeUtil.getTodayInt(), -2, Calendar.MONTH);
        //获取两个月前一天
        Long twoMonthAgoLastDay = DateTimeUtil.getTimestampByCalendarType(twoMonthAgo, -1, Calendar.DATE);
        //二次过滤条件满足超过2个月未结账的公司
        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("groupByStr", "corpid");
        param.put("greaterEqualThanDate", twoMonthAgoLastDay);
        param.put("antiSettlement", BasicConstant.ZERO);
        //获取2个月内已经结账的数据
        List<SettleAccountsEntity> settleAccountsEntities = settleAccountsModel.findEntitys(param);
        List<String> removeCorpidList = settleAccountsEntities.stream().map(SettleAccountsEntity::getCorpid).collect(Collectors.toList());
        if (CollectionsUtil.isNotEmpty(removeCorpidList)){
            corpidList.removeAll(removeCorpidList);
        }
        LOG.warn("共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        //组装参数进行自动结账
        SettleAccountsDTO settleAccountsDTO = new SettleAccountsDTO();
        settleAccountsDTO.setLoginUserName("系统自动");
        settleAccountsDTO.setUserId("system");
        //结账日期为2个月前的日期，产品说保持2个月未结账,取2个月前一天
        settleAccountsDTO.setDate(twoMonthAgoLastDay);
        boolean isGrayEnvironmentEnable = sysEnvHelp.isGrayEnvironmentEnable();
        for (String corpid : corpidList) {

            if (sysEnvHelp.isGrayEnvironment()) {
                if (!isGrayEnvironmentEnable) {
                    continue;
                }
                if (!sysEnvHelp.checkIsCrayCompany(corpid)) {
                    continue;
                }
            } else {
                if (isGrayEnvironmentEnable) {
                    if (sysEnvHelp.checkIsCrayCompany(corpid)) {
                        continue;
                    }
                }
            }

            LOG.warn("公司:" + corpid + "-------" + "开始刷入数据");
            try {
                //校验公司启用时间是否符合条件
                FeeCompanyEntity feeCompanyEntity = feeCompanyModel.getFirstFeeCompanyIgnoreIsPay(corpid);
                if (Objects.isNull(feeCompanyEntity)) {
                    LOG.error("公司ID是" + corpid + "没有收费记录");
                    continue;
                }
                if (Objects.nonNull(feeCompanyEntity)) {
                    if (feeCompanyEntity.getStartTime() > twoMonthAgoLastDay) {
                        LOG.error("公司ID是" + corpid + feeCompanyEntity.getStartTime().toString() + "是新创建公司，未达到自动结账日期要求");
                        continue;
                    }
                }
                settleAccountsDTO.setCorpid(corpid);
                SettleAccountsVO settleAccountsVO = settleAccountsService.addSettleAccounts(settleAccountsDTO);
            } catch (XbbException e) {
                LOG.error("失败了,公司ID是" + corpid + "错误信息" + e.getMsg());
                errorCorpidList.add(corpid);
            }
            ++corpidCount;
            LOG.warn("公司" + corpid + "/***总进度" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.error("失败的公司:" + errorCorpidList.toString());
        LOG.warn("自动结账 结束！");
        return "success";
    }


    /**
     * 清除结账中状态redis 缓存
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/cleanRedisValue", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String cleanRedisValue(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = new ArrayList<>();
        //支持传入公司
        if (Objects.nonNull(fixDataJobDTO.getCorpidList()) && !fixDataJobDTO.getCorpidList().isEmpty()) {
            corpidList = fixDataJobDTO.getCorpidList();
        }
        long start = DateTimeUtil.getInt();
        LOG.warn("清除 begin。。。。。。。");
        LOG.warn("共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            paasRedisHelper.removeValue(RedisPrefixConstant.SETTLE_ACCOUNTS, corpid);
            ++corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("清除redis缓存 结束！");
        return "success";
    }

    /**
     * 插入默认结账数据
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/defaultData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String insertDefaultData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        LOG.warn("插入默认结账数据 begin。。。。。。。");
        long startTime = DateTimeUtil.getInt();
        List<String> errorCorpidList = new ArrayList<>();
        List<String> corpidList = new ArrayList<>();
        //支持传入公司
        if (CollectionsUtil.isNotEmpty(fixDataJobDTO.getCorpidList())) {
            corpidList = fixDataJobDTO.getCorpidList();
        }else {
            //获取符合条件的公司-现在开启进销存公司列表
            corpidList = companyModel.getJxcCorpidListTemporary();
        }
        LOG.warn("查询进销存公司列表结束，花费时间:" + (DateTimeUtil.getInt() - startTime));
        LOG.warn("共有公司" + corpidList.size() + "家");
        //过滤系统启用日期小于六个月的公司
        Long defaultTime = BasicConstant.PRODUCT_COST_OPTIMIZE_DEFAULT_DATE;
        Map<String, Object> param = new HashMap<>(16);
        param.put("del", 0);
        param.put("alias", "JXC");
        param.put("corpidIn", corpidList);
        param.put("defaultTime", defaultTime);
        param.put("orderByStr", " add_time asc ");
        List<String> enableJxcCorpidList= paasAppModel.getJxcEnableTime(param);
        if (enableJxcCorpidList == null) {
            throw new XbbException(SettleAccountErrorCodeEnum.API_ERROR_254009);
        }
        LOG.warn("启用JXC小于六个月公司" + enableJxcCorpidList.size() + "家");
        corpidList.removeAll(enableJxcCorpidList);
        LOG.warn("需要处理的公司" + corpidList.size() + "家");
        int corpidCount = 0;
        //组装参数进行结账数据保存
        Long now = DateTimeUtil.getInt();
        SettleAccountsEntity settleAccountsEntity = new SettleAccountsEntity();
        settleAccountsEntity.setCheckOutTime(BasicConstant.PRODUCT_COST_OPTIMIZE_DEFAULT_DATE);
        settleAccountsEntity.setLastCheckOutTime(BasicConstant.PRODUCT_COST_OPTIMIZE_DEFAULT_DATE);
        settleAccountsEntity.setCheckOutUserId("system");
        settleAccountsEntity.setCheckOutUserName("系统自动");
        settleAccountsEntity.setAddTime(now);
        settleAccountsEntity.setUpdateTime(now);
        settleAccountsEntity.setDel(DelEnum.NORMAL.getDel());
        settleAccountsEntity.setAntiSettlement(BasicConstant.ZERO);
        for (String corpid : corpidList) {
            try {
                settleAccountsEntity.setCorpid(corpid);
                settleAccountsModel.insert(settleAccountsEntity);
            } catch (XbbException e) {
                LOG.warn("失败了,公司ID是" + corpid + "错误信息" + e.getMsg());
                errorCorpidList.add(corpid);
            }
            ++corpidCount;
            LOG.warn("公司" + corpid + "/" + corpidCount + "/" + corpidList.size());
        }

        LOG.warn("consume:" + (DateTimeUtil.getInt() - startTime));
        LOG.warn("失败的公司:" + errorCorpidList.toString());
        LOG.warn("生成默认结账数据 结束！");
        return "success";
    }


    /**
     * 清除结账中状态redis 缓存
     *
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/cleanSettleAccounts", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String cleanSettleAccounts(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = new ArrayList<>();
        //支持传入公司
        if (Objects.nonNull(fixDataJobDTO.getCorpidList()) && !fixDataJobDTO.getCorpidList().isEmpty()) {
            corpidList = fixDataJobDTO.getCorpidList();
        }else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        long start = DateTimeUtil.getInt();
        LOG.warn("清除 begin。。。。。。。");
        LOG.warn("共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            settleAccountsModel.cleanSettleAccounts(corpid);
            ++corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("清除结账数据结束！");
        return "success";
    }
}
